package com.yf.exam.modules.exam.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.core.enums.OpenType;
import com.yf.exam.core.exception.ServiceException;
import com.yf.exam.core.utils.BeanMapper;
import com.yf.exam.modules.exam.dto.ExamDTO;
import com.yf.exam.modules.exam.dto.ExamRepoDTO;
import com.yf.exam.modules.exam.dto.ext.ExamRepoExtDTO;
import com.yf.exam.modules.exam.dto.request.ExamSaveReqDTO;
import com.yf.exam.modules.exam.dto.response.ExamOnlineRespDTO;
import com.yf.exam.modules.exam.dto.response.ExamReviewRespDTO;
import com.yf.exam.modules.exam.entity.Exam;
import com.yf.exam.modules.exam.mapper.ExamMapper;
import com.yf.exam.modules.exam.service.ExamDepartService;
import com.yf.exam.modules.exam.service.ExamRepoService;
import com.yf.exam.modules.exam.service.ExamService;
import com.yf.exam.modules.paper.entity.ExamApply;
import com.yf.exam.modules.paper.service.ExamApplyService;
import com.yf.exam.modules.sys.user.entity.SysUser;
import com.yf.exam.modules.sys.user.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 考试业务实现类
 * </p>
 *
 * @author 聪明笨狗
 * @since 2020-07-25 16:18
 */
@Slf4j
@Service
public class ExamServiceImpl extends ServiceImpl<ExamMapper, Exam> implements ExamService {
    @Autowired
    private ExamRepoService examRepoService;
    @Autowired
    private ExamDepartService examDepartService;
    @Autowired
    private ExamApplyService examApplyService;
    @Autowired
    private SysUserService sysUserService;

    @Override
    public void save(ExamSaveReqDTO reqDTO) {
        if (Objects.isNull(reqDTO.getOpenType())) { // 未传时，设置为完全开放
            reqDTO.setOpenType(OpenType.OPEN);
        }
        // ID
        String id = reqDTO.getId();
        if (StringUtils.isBlank(id)) {
            id = IdWorker.getIdStr();
        }
        //复制参数
        Exam entity = new Exam();
        // 计算分值
        this.calcScore(reqDTO);
        // 复制基本数据
        BeanMapper.copy(reqDTO, entity);
        entity.setId(id);
        // 修复状态
        if (reqDTO.getTimeLimit() != null
                && !reqDTO.getTimeLimit()
                && reqDTO.getState() != null
                && reqDTO.getState() == 2) {
            entity.setState(0);
        } else {
            entity.setState(reqDTO.getState());
        }
        // 题库组卷
        try {
            examRepoService.saveAll(id, reqDTO.getRepoList());
        } catch (DuplicateKeyException e) {
            throw new ServiceException(1, "不能选择重复的题库！");
        }
        // 开放的部门
        if (OpenType.DEPT_OPEN.equals(reqDTO.getOpenType())) {
            examDepartService.saveAll(id, reqDTO.getDepartIds());
        }
        this.saveOrUpdate(entity);
    }

    @Override
    public ExamSaveReqDTO findDetail(String id) {
        ExamSaveReqDTO respDTO = new ExamSaveReqDTO();
        Exam exam = this.getById(id);
        BeanMapper.copy(exam, respDTO);
        // 考试部门
        List<String> departIds = examDepartService.listByExam(id);
        respDTO.setDepartIds(departIds);
        // 题库
        List<ExamRepoExtDTO> repos = examRepoService.listByExam(id);
        respDTO.setRepoList(repos);
        return respDTO;
    }

    @Override
    public ExamDTO findById(String id) {
        ExamDTO respDTO = new ExamDTO();
        Exam exam = this.getById(id);
        BeanMapper.copy(exam, respDTO);
        return respDTO;
    }

    @Override
    public IPage<ExamDTO> paging(PagingReqDTO<ExamDTO> reqDTO) {
        //创建分页对象
        Page page = reqDTO.toPage();
        //转换结果
        IPage<ExamDTO> pageData = baseMapper.paging(page, reqDTO.getParams());
        return pageData;
    }

    @Override
    public IPage<ExamOnlineRespDTO> onlinePaging(PagingReqDTO<ExamDTO> reqDTO, String userId) {
        QueryWrapper<ExamApply> examApplyWrapper = new QueryWrapper<>();
        String userName;
        SysUser sysUser = sysUserService.getById(userId);
        if (Objects.nonNull(sysUser)) {
            userName = sysUser.getUserName();
        } else {
            userName = null;
        }
        examApplyWrapper
                .lambda()
                .eq(ExamApply::getIsApply, 1)
                .and(qu -> qu
                        .eq(Objects.nonNull(userName), ExamApply::getUserName, userName)
                        .or()
                        .eq(Objects.nonNull(userName), ExamApply::getPhone, userName)
                )
                .orderByDesc(ExamApply::getCreateTime)
                .last(" LIMIT 1 "); // 查出最新的已通过的考试申请
        ExamApply examApply = examApplyService.getBaseMapper().selectOne(examApplyWrapper);
        log.info("当前用户 {} 对应的申请id:{}", userName, Objects.nonNull(examApply) ? examApply.getId() : null);
        // 创建分页对象
        Page page = reqDTO.toPage();
        // 查找分页
        IPage<ExamOnlineRespDTO> pageData = baseMapper.online(page, reqDTO.getParams(), userId,
                Objects.nonNull(examApply) ? examApply.getId() : null);
        return pageData.convert(item -> {
            if (Objects.nonNull(examApply)) {
                item.setApplyId(examApply.getId()); // 回填最新申请通过的对应申请记录id
                item.setAllPass(examApply.getAllPass()); // 回填申请的全局状态
            }
            if (item.getPassed()) {
                item.setExamStatus(2); // 2.通过
                return item;
            }
            if (item.getExamCount() <= 0) {
                item.setExamStatus(0); // 未考试
                return item;
            }
            if (item.getExamCount() <= 3) {
                item.setExamStatus(1); //考试中
                return item;
            }
            item.setExamStatus(3); // 未通过
            item.setApplyId(Objects.nonNull(examApply) ? examApply.getId() : null);
            return item;
        });
    }

    @Override
    public IPage<ExamReviewRespDTO> reviewPaging(PagingReqDTO<ExamDTO> reqDTO) {
        // 创建分页对象
        Page page = reqDTO.toPage();
        // 查找分页
        IPage<ExamReviewRespDTO> pageData = baseMapper.reviewPaging(page, reqDTO.getParams());
        return pageData;
    }


    /**
     * 计算分值
     *
     * @param reqDTO
     */
    private void calcScore(ExamSaveReqDTO reqDTO) {
        // 主观题分数
        int objScore = 0;
        // 题库组卷
        List<ExamRepoExtDTO> repoList = reqDTO.getRepoList();
        for (ExamRepoDTO item : repoList) {
            if (item.getRadioCount() != null
                    && item.getRadioCount() > 0
                    && item.getRadioScore() != null
                    && item.getRadioScore() > 0) {
                objScore += item.getRadioCount() * item.getRadioScore();
            }
            if (item.getMultiCount() != null
                    && item.getMultiCount() > 0
                    && item.getMultiScore() != null
                    && item.getMultiScore() > 0) {
                objScore += item.getMultiCount() * item.getMultiScore();
            }
            if (item.getJudgeCount() != null
                    && item.getJudgeCount() > 0
                    && item.getJudgeScore() != null
                    && item.getJudgeScore() > 0) {
                objScore += item.getJudgeCount() * item.getJudgeScore();
            }
        }
        reqDTO.setTotalScore(objScore);
    }

}
